<template>
  <div class="pane">
    <div class="head" style="padding-right: 8px;">
      <span>字典列表</span>
      <div style="flex: 1;"></div>
      <el-button type="primary" @click="handleAdd" size="small">
        <el-icon><Plus /></el-icon>新增字典
      </el-button>
    </div>
    <div class="body">
      <div class="search-bar">
        <el-input
          v-model="keywords"
          placeholder="输入字典名称或编码搜索"
          clearable
          @keyup.enter="handleSearch"
        >
          <template #append>
            <el-button icon="Search" @click="handleSearch" />
          </template>
        </el-input>
      </div>

      <el-tree
        ref="treeRef"
        v-loading="loading"
        :data="treeData"
        :props="{
          label: 'name',
          children: 'children'
        }"
        node-key="id"
        highlight-current
        :current-node-key="currentKey"
        :expand-on-click-node="false"
        @node-click="handleNodeClick"
        @node-contextmenu="handleContextMenu"
      >
        <template #default="{ node, data }">
          <div class="custom-tree-node">
            <span class="label">{{ data.name }}</span>
            <!-- <span class="code">({{ data.code }})</span> -->
          </div>
        </template>
      </el-tree>

      <!-- 右键菜单 -->
      <ul
        v-show="contextMenu.visible"
        :style="{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }"
        class="context-menu"
      >
        <li @click="handleContextMenuClick('edit')">
          <el-icon><Edit /></el-icon>
          编辑字典
        </li>
        <li @click="handleContextMenuClick('delete')">
          <el-icon><Delete /></el-icon>
          删除字典
        </li>
      </ul>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount, watch } from 'vue';
import type { TreeInstance } from 'element-plus';
import DictAPI, { type Dict } from '@/api/system/dict';

const props = defineProps({
  modelValue: {
    type: String,
    default: ''
  }
});

const emit = defineEmits(['update:modelValue', 'node-click']);

const treeRef = ref<TreeInstance>();
const loading = ref(false);
const keywords = ref('');
const treeData = ref<Dict[]>([]);
const currentKey = ref('');

// 右键菜单状态
const contextMenu = reactive({
  visible: false,
  x: 0,
  y: 0,
  node: null as Dict | null
});

// 加载树数据
const loadTree = async () => {
  try {
    loading.value = true;
    const data = await DictAPI.getTree(keywords.value);
    treeData.value = buildTree(data);
  } finally {
    loading.value = false;
  }
};

// 递归构建树形数据
const buildTree = (items: Dict[], parentId: string = '-1'): Dict[] => {
  const result: Dict[] = [];
  for (const item of items) {
    if (item.parentId === parentId) {
      const children = buildTree(items, item.id);
      if (children.length) {
        item.children = children;
      }
      result.push(item);
    }
  }
  return result;
};

// 搜索
const handleSearch = () => {
  loadTree();
};

// 处理节点点击
const handleNodeClick = (data: Dict) => {
  currentKey.value = data.id;
  emit('update:modelValue', data.id);
  emit('node-click', data);
};

// 新增
const handleAdd = () => {
  emit('node-click', { type: 'add' });
};

// 处理右键菜单
const handleContextMenu = (event: MouseEvent, data: Dict) => {
  event.preventDefault();
  contextMenu.visible = true;
  contextMenu.x = event.clientX;
  contextMenu.y = event.clientY;
  contextMenu.node = data;
};

// 处理右键菜单点击
const handleContextMenuClick = (type: 'edit' | 'delete') => {
  if (!contextMenu.node) return;
  
  if (type === 'edit') {
    emit('node-click', { type: 'edit', data: contextMenu.node });
  } else {
    emit('node-click', { type: 'delete', data: contextMenu.node });
  }
  hideContextMenu();
};

// 隐藏右键菜单
const hideContextMenu = () => {
  contextMenu.visible = false;
  contextMenu.node = null;
};

// 点击其他地方关闭右键菜单
const handleClickOutside = (event: MouseEvent) => {
  const menu = document.querySelector('.context-menu');
  if (menu && !menu.contains(event.target as Node)) {
    hideContextMenu();
  }
};

// 监听 modelValue 变化
watch(() => props.modelValue, (val) => {
  if (val) {
    currentKey.value = val;
  }
}, { immediate: true });

onMounted(() => {
  loadTree();
  document.addEventListener('click', handleClickOutside);
  document.addEventListener('contextmenu', handleClickOutside);
});

onBeforeUnmount(() => {
  document.removeEventListener('click', handleClickOutside);
  document.removeEventListener('contextmenu', handleClickOutside);
});
</script>

<style lang="scss" scoped>
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  font-size: 14px;
  padding-right: 8px;
  
  .label {
    font-weight: 500;
  }
  
  .code {
    color: var(--el-text-color-secondary);
    margin-left: 8px;
    font-size: 12px;
  }
  
  .status {
    margin-left: 8px;
  }
}

.context-menu {
  position: fixed;
  z-index: 9999;
  background: white;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  padding: 8px 0;
  margin: 0;
  list-style: none;
  
  li {
    padding: 8px 16px;
    cursor: pointer;
    display: flex;
    align-items: center;
    font-size: 14px;
    color: var(--el-text-color-regular);
    
    .el-icon {
      margin-right: 8px;
      font-size: 16px;
    }
    
    &:hover {
      background-color: var(--el-fill-color-light);
      color: var(--el-color-primary);
    }
  }
}

:deep(.el-tree-node__content) {
  height: 32px;
  
  &:hover {
    background-color: var(--el-fill-color-light);
  }
}

:deep(.el-tree-node.is-current > .el-tree-node__content) {
  background-color: var(--el-color-primary-light-9);
  color: var(--el-color-primary);
  
  .custom-tree-node {
    .label {
      color: var(--el-color-primary);
      font-weight: bold;
    }
    
    .code {
      color: var(--el-color-primary-light-3);
    }
  }
}
</style> 